const puppeteerEx = require('puppeteer-extra')
const StealthPlugin = require('puppeteer-extra-plugin-stealth')
let page;
let cVideoInfo = {
    nickname: '',
    uid: '',
    short_id: '',
    title: '',
    coverImg: '',
    statistics: {
        aweme_id: "",
        comment_count: 0,
        digg_count: 0,
        play_count: 0
    }
};
let videoInfoCallback;
const cRes = {
    code: 0,
    data: '',
    msg: ''
};

async function puptrInit() {
    puppeteerEx.use(StealthPlugin());
    const browser = await puppeteerEx.launch({
        args: ['--no-sandbox', '--disable-setuid-sandbox'],
        ignoreDefaultArgs: ["--enable-automation"],
        headless: true, //默认为true（无头），不显示浏览器界面
        // slowMo: 200, //减速显示，有时会作为模拟人操作特意减速
        // devtools: false, //显示开发者工具。页面宽高默认800*600,把开发者工具显示再隐藏页面会占满屏幕，有没有大佬解释下？
    });
    await browser.on('targetcreated', async (target) => {
        if (target.type() !== 'page') {
            return;
        } else {
            console.log('new page!');
            const newPage = await target.page();
            // await newPage.setDefaultNavigationTimeout(15 * 1000)
            await newPage.setViewport({
                width: 1200,
                height: 900,
                deviceScaleFactor: 1,
            });
            // await newPage.setRequestInterception(true);
            await newPage.on('response', async res => {
                if (res.url().indexOf('https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids') != -1) {
                    let body = await res.text();
                    console.log(body);
                    body = JSON.parse(body);
                    let videoInfo = { ...cVideoInfo };
                    videoInfo.nickname = body.item_list[0].author.nickname;
                    videoInfo.uid = body.item_list[0].author.uid;
                    videoInfo.short_id = body.item_list[0].author.short_id;
                    videoInfo.title = body.item_list[0].share_info.share_title;
                    videoInfo.coverImg = body.item_list[0].video.cover.url_list[0];
                    videoInfo.statistics = body.item_list[0].statistics;
                    if (videoInfoCallback) {
                        videoInfoCallback(videoInfo)
                        videoInfoCallback = null;
                    }
                }
            });
            // Bypass hairline feature
            await newPage.evaluateOnNewDocument(() => {
                // store the existing descriptor
                const elementDescriptor = Object.getOwnPropertyDescriptor(
                    HTMLElement.prototype,
                    "offsetHeight"
                );

                // redefine the property with a patched descriptor
                Object.defineProperty(HTMLDivElement.prototype, "offsetHeight", {
                    ...elementDescriptor,
                    get: function () {
                        if (this.id === "modernizr") {
                            return 1;
                        }
                        // @ts-ignore
                        return elementDescriptor.get.apply(this);
                    },
                });
            });
        }
    });
    page = await browser.newPage();
    pages = await browser.pages();
    await pages[0].close();
    console.log('puppeteer内核启动成功');
}

async function getVideoInfo(url) {
    if (page == null) {
        console.log('puppeteer内核还没有启动')
        return;
    }
    console.log('开始加载url: ' + url);
    return await getResult(url);
}

async function getResult(url) {
    let gotoPromise = page.goto(url, { timeout: 15000, waitUntil: 'networkidle0' })
        .then(response => {
            let res = { ...cRes };
            res.code = 1;
            res.msg = 'url加载完成: code = ' + response.status() + (response.ok() ? " (OK)" : " (ERROR)");
            return res;
        })
        .catch(err => {
            let res = { ...cRes };
            res.code = 1;
            res.msg = 'url加载错误: ' + JSON.stringify(err);
            return res;
        });

    let resultPromise = new Promise((resolve, reject) => {
        videoInfoCallback = function (videoInfo) {
            let res = { ...cRes };
            res.data = videoInfo;
            resolve(res);
        };
    })

    let totalPromise = Promise.race([gotoPromise, resultPromise])
        .then(data => {
            console.log('res ok: ' + JSON.stringify(data))
            return data
        })
        .catch(err => {
            console.log('res err: ' + JSON.stringify(err))
            throw err
        })

    return totalPromise;
}

module.exports = {
    puptrInit,
    getVideoInfo
}